PurgeMemSys
PurgeMem Purge blocks without compacting the heap
#include <Memory.h> Memory Manager
void PurgeMem( bytesNeeded );
Size bytesNeeded ; size of contiguous block to locate
PurgeMem performs a partial or complete purge of purgeable, unlocked,
relocatable blocks in the current heap zone. Purgeable blocks are removed
until a specified-size block is found or until all purgeable blocks are purged.
Compaction is not performed.
bytesNeeded is the size of a block you wish to allocate in a subsequent call to
NewPtr or NewHandle. Blocks are purged until a bytesNeeded
block of memory becomes available or until the purge is complete. As
a Size type, it should be less than 16M (a 24-bit value).
Returns: none; the MemError function may return an Error Code of:
noErr (0) No error
memFullErr (-108) A bytesNeeded -length block was not found

Notes: There is another routine, PurgeMemSys, which performs the equivalent
operation to PurgeMem, but in the System heap zone. It takes the same
parameters as PurgeMem.
This may be faster than other functions that move blocks of memory (such
as CompactMem or MaxMem) in searching for free blocks. Only
relocatable blocks explicitly tagged as purgeable (see HPurge) and
currently unlocked (see HUnlock) will be purged.
PurgeMem does not allocate any memory.
Use PurgeSpace or MaxBlock to see how much memory will be obtained
if you call PurgeMem.
The following information is from Apple's Macintosh Technical Note #303.
Inside Macintosh, Volume 2, page 23 briefly discusses purgeProc's. Most
applications will never need to use a purgeProc. However, if your
application requires the ability to maintain purgeable handles containing
data, or you need to have special notification when a certain handle is
purged, a purgeProc might help.
The purgeProc is the mechanism which allows the Memory Manager to
alert your application that it is getting ready to purge a given purgeable
handle. This warning is given so that you can save the data, or note for any
special reason that the data no longer exists. The purgeProc is passed the
handle that is being purged. It is up to you to determine if any action should
be taken on the handle. The interface looks like this:
pascal void myPurgeProc (Handle theHandle);
Each zone has its own purgeProc pointer in its zone header. Each time the
Memory Manager prepares to purge a handle, it checks the zone header of the
zone that the handle belongs to, to determine if your application has
installed a purgeProc. If this field is not NIL, it calls the routine pointed to
with the handle being purged. This occurs for each handle being purged (not
every purgeable handle necessarily). When your routine is called, test the
handle passed to be sure that it is a handle you care about, then act on it.
Keep in mind that all handles that pass through your purgeProc may not be
expected, since your application can create purgeable handles in a few ways,
like calling HPurge on an existing handle, or loading a resource (the
resource could have the purgeable attribute set), or by calling a routine
that could load a resource.
You install your own purgeProc by setting the field in your zone header.
Here is a sample routine that installs a purgeProc:
void InstallProc()
{
THz myZone;
myZone = GetZone(); /* recover my application's zone */
gOldProc = myZone->purgeProc; /* save the old purgeProc */
/* the name of the function is the address of the function */
myZone->purgeProc = myPurgeProc;
}
You must be sure to follow these rules regarding what a purgeProc must,
can, and cannot do...
Do not rely on A5 being set to your application's globals. See
SetA5 and SetCurrentA5 for more information.
Do not cause memory to be moved or purged.
Do not open a file (but you can write to an already open file).
Do not dispose of or change the purge status of the passed handle.
Only use purgeProcs when absolutely necessary.
Avoid using purgeProcs if you are also using the
SetResPurge(true) feature.
Use synchronous writes to data files.
Preserve the contents of registers except A0-A2/D0/D1
Use the FoldFolder feature of System 7.0 to locate the temporary
folder on the user's hard disk if you are creating a temporary file
to hold the contents of purged handles.
Test the handle state first to determine if the handle belongs to the
Resource Manager, to weed out most handle purges that you don't
care about.
Don't take too long to determine if the passed handle is in need of
purge notification (many programmers do not realize how often a
purgeProc is called).
Here is a pseudo code example that illustrates one possible use of the purge
warning procedure: saving the contents of the handle to a file before purging:
PurgeWarning( myHandleType theHandle)
{
SetUpApplicationA5World();
if(!((HGetState( theHandle) & 0x20))
//if we get here, the handle does not belong to a resource
if(InSaveList( theHandle))
WriteData( theHandle);
}
Remember, the save file should probably be open at this point because opening a
file can cause memory to move. You will have to maintain a save list to indicate
purgeable handles that need saving.
If you plan to use the SetResPurge(true) option that allows you to modify
purgeable resources (not a normal thing for applications to do). don't patch the
purgeProc pointer. If you do, remove your purgeProc, call SetResPurge, then
re-install the purgeProc, making sure that it calls through to the Resource
Manager's routine after it is finished.